package org.xs.web.http.provider.servlet;

import java.io.IOException;
import java.io.Writer;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.VelocityException;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.xs.web.http.S;
import org.xs.web.http.XSRules;
import org.xs.web.http.provider.HTTPRequest;
import org.xs.web.http.provider.HTTPResponse;
import org.xs.web.http.velocity.VelocityConfigurer;

public abstract class HTTPFilterProvider implements Filter{
	protected ServletContext servletContext;
	protected ApplicationContext appContext;
	protected VelocityEngine velocityEngine;
	@Override
	public void destroy() {
	}

	
	
	@Override
	final public void doFilter(ServletRequest req, ServletResponse res,FilterChain chain) throws IOException, ServletException{
		if(!(req instanceof HttpServletRequest) || !isXsService(((HttpServletRequest)req).getServletPath())){
			chain.doFilter(req, res);
			return;
		}
		req.setCharacterEncoding(XSRules.Encode);
	 
		HTTPServletContext ctx = new HTTPServletContext(getServletContext());
		HTTPServletRequest httpReq = new HTTPServletRequest(ctx, (HttpServletRequest)req,new HTTPServletSession(((HttpServletRequest)req).getSession(true)));
		HTTPServletResponse httpResp = new HTTPServletResponse((HttpServletResponse)res);
		try {
			S.init(this,httpReq, httpResp,ctx,getApplicationContext());
			doService(httpReq, httpResp);
			 
		} catch (Exception e) {
			throw new ServletException(e);
		}finally{
			S.shutdown(this);
		}
	}
	
	
	public abstract boolean isXsService(String path);
	public abstract void doService(HTTPRequest request,HTTPResponse response);
	
	
	protected ServletContext getServletContext() {
		return servletContext;
	}

	@Override
	final public void init(FilterConfig config) throws ServletException,VelocityException {
		servletContext = config.getServletContext();
		XSRules.ctxPath = servletContext.getContextPath();
		try {
			initTemplate();
		} catch (IOException e) {
			throw new ServletException(e); 
		}	 
		boot();
	}


	private void initTemplate() throws IOException {
		VelocityConfigurer templateConfig = new VelocityConfigurer(servletContext); 
		velocityEngine = templateConfig.createVelocityEngine();
		XSRules.velocityEngine = velocityEngine;
	}
	
	public abstract void boot();	

	
	final public synchronized ApplicationContext getApplicationContext() {
		if(appContext == null){
			appContext =WebApplicationContextUtils.getWebApplicationContext(getServletContext());
		}
		assert(appContext != null);
		return appContext;
	}



	public ApplicationContext getAppContext() {
		return appContext;
	}

	public VelocityEngine getVelocityEngine() {
		return velocityEngine;
	}
	
	 
	
	protected void render(HttpServletResponse response,String layoutContextAsString) {
		response.addHeader("Content-Length", String.format("%s", new Object[]{layoutContextAsString.getBytes().length}));
		response.addHeader("Power-By", "XS");
		response.addHeader("Content-Type", "text/html;charset=utf-8");
		Writer write = null;
		try {
			write = response.getWriter();
			write.write(layoutContextAsString);
		} catch (Exception e) {
		}finally{
			if(write != null){
				try {
					write.flush();
					write.close();
				} catch (IOException e) {
				}
			}
		}
	}
}
